package com.example.protocol.mqtt;

import com.example.protocol.util.TopicMatch;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;

/**
 * mqtt客户端，构造器私有，建议用Spring注解Autowired使用，这样能够保持单例
 */
@Component //Component默认是单例模式
public class MQTTClient extends MQTTConfig implements MqttCallback {

    private MqttClient mqttClient = null;

    private static final Logger logger = LoggerFactory.getLogger(MQTTClient.class);

    private MQTTClient() {
        String ipUrl = this.TCP + this.ip + ":" + this.port;
        MemoryPersistence persistence = new MemoryPersistence();
        MqttConnectOptions connectionOptions = new MqttConnectOptions();
        try {
            this.mqttClient = new MqttClient(ipUrl, clientId, persistence);
            connectionOptions.setCleanSession(true);
            connectionOptions.setUserName(username);
            connectionOptions.setPassword(password.toCharArray());
            this.mqttClient.connect(connectionOptions);
            this.mqttClient.setCallback(this);
        } catch (MqttException me) {
            logger.error("ERROR", me);
        }
    }


    /**
     * 发布消息
     *
     * @param topic   主题
     * @param message 消息
     */
    public void publishMessage(String topic, String message) {
        try {
            MqttMessage mqttmessage = new MqttMessage(message.getBytes());
            mqttmessage.setQos(0);
            this.mqttClient.publish(topic, mqttmessage);
        } catch (MqttException me) {
            logger.error("ERROR", me);
        }
    }

    /**
     * 发布消息之后的回调函数
     *
     * @param arg0 IMqttDeliveryToken
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken arg0) {
        logger.info("delivery completed");
    }

    /**
     * 订阅消息
     *
     * @param topic 主题
     */
    public void subscribeMessage(String topic) {
        try {
            this.mqttClient.subscribe(topic, 1);
        } catch (MqttException me) {
            me.printStackTrace();
        }
    }

    /**
     * 收到消息之后的回调函数
     *
     * @param topic   订阅的主题
     * @param message 接收到的消息内容
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        logger.info("收到消息，topic: {}", topic);
        for (CallBackHandler handler :
                MQTTRunner.subscribeTopicHandlerList) {
            if (TopicMatch.mqttTopicMatch(topic, handler.getHandleableTopic())) {

//                try {
                    HandlerThread handlerThread = null;

//                    handlerThread = new HandlerThread(message, (CallBackHandler) Class.forName(handler.getClass().getName()).getDeclaredConstructor().newInstance());
                    handlerThread = new HandlerThread(message, (CallBackHandler) handler.clone());
                    handlerThread.run();
//                } catch (ClassNotFoundException | NoSuchMethodException e) {
//                    e.printStackTrace();
//                } catch (InvocationTargetException e) {
//                    e.printStackTrace();
//                } catch (InstantiationException e) {
//                    e.printStackTrace();
//                } catch (IllegalAccessException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }


    /**
     * 断开MQTT客户端
     */
    public void disconnect() {
        try {
            this.mqttClient.disconnect();
        } catch (MqttException me) {
            logger.error("ERROR", me);
        }
    }


    /**
     * 意外断开的回调函数
     *
     * @param arg0 Throwable
     */
    @Override
    public void connectionLost(Throwable arg0) {
        logger.error("Connection Lost");
        arg0.printStackTrace();

    }


}
